home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 1 / The Arsenal Files (Arsenal Computer).ISO / genprog / msjfeb94.exe / WIN32QA.ZIP / DFSRCDEM.C < prev    next >
C/C++ Source or Header  |  1994-02-01  |  9KB  |  350 lines

  1. /*************************************************************
  2. Module name: DFSrcDem.C
  3. Notices: Copyright (c) 1993 Jeffrey Richter
  4. *************************************************************/
  5.  
  6.  
  7. #include <windows.h>
  8. #include <windowsx.h>
  9. #include <tchar.h>
  10. #include <stdio.h>
  11.  
  12. #include "DFSrc.h"
  13.  
  14. #define ARRAY_LEN(Array) (sizeof(Array) / sizeof(Array[0]))
  15.  
  16.  
  17. //////////////////////////////////////////////////////////////
  18.  
  19.  
  20. // Utility function that parses the list of selected files 
  21. // returned by the File Open Common Dialog Box.
  22. int GetSinglePathName (LPCTSTR szFileOpenStr, int nIndex,
  23.         LPTSTR szPathName, int nMaxLen);
  24.  
  25.  
  26. //////////////////////////////////////////////////////////////
  27.  
  28.  
  29. HINSTANCE g_hInstance;
  30. TCHAR g_szAppName[] = __TEXT("Drop File Source Application");
  31. static TCHAR g_szAllFileNames[1000]  = { 0 };
  32.  
  33.  
  34.  
  35. //////////////////////////////////////////////////////////////
  36.  
  37.  
  38. void Dlg_OnUpdateCaption (HWND hwnd, int nNumFiles) {
  39.     TCHAR szBuf[100];
  40.     // Update the window's caption to reflect  the number
  41.     // of selected files available for dropping
  42.     _stprintf(szBuf, __TEXT("%s - %d file(s) to drop"),
  43.         g_szAppName, nNumFiles);
  44.     SetWindowText(hwnd, szBuf);
  45. }
  46.  
  47.  
  48. //////////////////////////////////////////////////////////////
  49.  
  50.  
  51. BOOL Dlg_OnInitDialog (HWND hwnd, HWND hwndFocus, 
  52.     LPARAM lParam) {
  53.  
  54.    SetClassLong(hwnd, GCL_HICON, (LONG)
  55.        LoadIcon((HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
  56.           __TEXT("DFSrcDem")));
  57.  
  58.     Dlg_OnUpdateCaption (hwnd, 0);
  59.     return(TRUE);
  60. }
  61.  
  62.  
  63. //////////////////////////////////////////////////////////////
  64.  
  65.  
  66. void Dlg_OnCommand (HWND hwnd, int id, 
  67.     HWND hwndCtl, UINT codeNotify) {
  68.  
  69.     OPENFILENAME ofn;
  70.     int nNumFiles;
  71.  
  72.     switch (id) {
  73.         case 100:    // "File Select!" menu item
  74.             // Initialize structure for calling
  75.             // the "Open File" common dialog
  76.             memset(&ofn, 0, sizeof(ofn));
  77.             ofn.lStructSize = sizeof(ofn);
  78.             ofn.hwndOwner = hwnd;
  79.             ofn.lpstrFilter = __TEXT("All files\0*.*\0");
  80.             ofn.Flags = OFN_ALLOWMULTISELECT | 
  81.                 OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  82.  
  83.             // Set up the buffer to receive the selected file(s)
  84.             g_szAllFileNames[0] = 0;
  85.             ofn.lpstrFile = g_szAllFileNames;
  86.             ofn.nMaxFile = ARRAY_LEN(g_szAllFileNames);
  87.  
  88.             if (GetOpenFileName(&ofn)) {
  89.                 nNumFiles = GetSinglePathName(g_szAllFileNames, 
  90.                     -1, NULL, 0);
  91.             } else {
  92.                 nNumFiles = 0;
  93.             }
  94.  
  95.             Dlg_OnUpdateCaption(hwnd, nNumFiles);
  96.             break;
  97.  
  98.         case IDCANCEL:
  99.             EndDialog(hwnd, id);
  100.             break;
  101.     }
  102. }
  103.  
  104.  
  105. //////////////////////////////////////////////////////////////
  106.  
  107.  
  108. // Macro to ease source code readability.
  109. #define WndAcceptsFiles(hwnd) \
  110.     (GetWindowExStyle((hwnd)) & WS_EX_ACCEPTFILES)
  111.  
  112.  
  113. void Dlg_OnLButtonDown (HWND hwnd, BOOL fDoubleClick, 
  114.     int x, int y, UINT keyFlags) {
  115.  
  116.     int nNumFiles;
  117.     HCURSOR hcurDrpNo, hcurDrpOk;
  118.     POINT ptMousePos;
  119.     HWND hwndSubject;
  120.     HDROP hDrop, hDropT;
  121.     BOOL fInNonClientArea, fOkToDrop;
  122.     TCHAR szDropPathName[200];
  123.  
  124.     // User has initiated the "Drag and Drop" sequence
  125.  
  126.     // Make sure that there are some files to be dropped
  127.     nNumFiles = 
  128.         GetSinglePathName(g_szAllFileNames, -1, NULL, 0);
  129.     if (nNumFiles == 0) {
  130.         MessageBox(hwnd, __TEXT("No files to drop."),
  131.             g_szAppName, MB_ICONINFORMATION | MB_OK);
  132.         return;
  133.     }
  134.  
  135.     // Get the handles to the cursors to show to the user.
  136.     hcurDrpNo = LoadCursor(NULL, IDC_NO);
  137.     hcurDrpOk = LoadCursor(g_hInstance,
  138.         (nNumFiles > 1) ? __TEXT("DrpMany") : __TEXT("DrpOne"));
  139.  
  140.  
  141.     // *** Loop for determining the drop-file client window ***
  142.     SetCapture(hwnd);
  143.     do {
  144.         // Get cursor position & window under the cursor
  145.         GetCursorPos(&ptMousePos);
  146.         hwndSubject = WindowFromPoint(ptMousePos);
  147.  
  148.         // See if the subject window or any of its parent 
  149.         // windows are prepared to accept dropped files.
  150.         while (IsWindow(hwndSubject)) {
  151.             if (WndAcceptsFiles(hwndSubject))
  152.                 break;
  153.           hwndSubject = GetParent(hwndSubject);
  154.         }
  155.  
  156.         fOkToDrop = IsWindow(hwndSubject) && 
  157.             WndAcceptsFiles(hwndSubject);
  158.  
  159.         SetCursor(fOkToDrop ? hcurDrpOk : hcurDrpNo);
  160.  
  161.        // Continue loop while the mouse button is pressed
  162.     } while (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
  163.     ReleaseCapture();
  164.  
  165.     // Free the loaded cursor from memory
  166.     DestroyCursor(hcurDrpOk);
  167.  
  168.  
  169.     if (!fOkToDrop) 
  170.         return;
  171.  
  172.     // Is the cursor in the window's non-client area?
  173.     fInNonClientArea = (HTCLIENT != 
  174.         FORWARD_WM_NCHITTEST(hwndSubject, 
  175.             ptMousePos.x, ptMousePos.y, SendMessage));
  176.  
  177.  
  178.     // Create drop-file memory block and initialize it
  179.     ScreenToClient(hwndSubject, &ptMousePos);
  180. #ifdef UNICODE
  181.     hDrop = DragCreateFiles(&ptMousePos, 
  182.         fInNonClientArea, TRUE);
  183. #else
  184.     hDrop = DragCreateFiles(&ptMousePos, 
  185.         fInNonClientArea, FALSE);
  186. #endif
  187.     if (hDrop == NULL) {
  188.         MessageBox(hwnd, 
  189.             __TEXT("Insufficient memory to drop file(s)."),
  190.             g_szAppName, MB_OK | MB_ICONSTOP);
  191.       return;
  192.     }
  193.  
  194.  
  195.     // Append each pathname to the drop-file memory block
  196.     for (x = 0; x < nNumFiles; x++) {
  197.         // Get the full pathname to append
  198.         GetSinglePathName(g_szAllFileNames, x, 
  199.             szDropPathName, ARRAY_LEN(szDropPathName));
  200.  
  201.       // Append pathname to end of drop-file memory block
  202.       hDropT = DragAppendFile(hDrop, (LPBYTE) szDropPathName);
  203.  
  204.         if (hDropT == NULL) {
  205.             MessageBox(hwnd, 
  206.                 __TEXT("Insufficient memory to drop file(s)."),
  207.                 g_szAppName, MB_OK | MB_ICONSTOP);
  208.          hDrop = GlobalFree(hDrop);
  209.          break;  // Terminate the 'for' loop
  210.        } else {
  211.             hDrop = hDropT;
  212.       }
  213.     }
  214.  
  215.     if (hDrop != NULL) {
  216.         // All pathnames appended successfully, post the 
  217.         // message to the drop-file client window
  218.         FORWARD_WM_DROPFILES(hwndSubject, hDrop, PostMessage);
  219.  
  220.         // Clear our own state information.
  221.         g_szAllFileNames[0] = 0;
  222.         Dlg_OnUpdateCaption(hwnd, 0);
  223.  
  224.         // Don't free the memory, the Dropfile client will do it
  225.     }
  226. }
  227.  
  228.  
  229. //////////////////////////////////////////////////////////////
  230.  
  231.  
  232. // The normal HANDLE_MSG macro in WINDOWSX.H does not work
  233. // properly for dialog boxes because DlgProc's return a BOOL
  234. // instead of an LRESULT (like WndProcs).  This HANDLE_DLGMSG
  235. // macro corrects the problem:
  236. #define HANDLE_DLGMSG(hwnd, message, fn)    \
  237.     case (message): return \
  238.         SetDlgMsgResult(hwnd, uMsg, \
  239.         HANDLE_##message((hwnd), (wParam), (lParam), (fn)))
  240.  
  241.  
  242. BOOL CALLBACK Dlg_Proc (HWND hwnd, UINT uMsg, 
  243.     WPARAM wParam, LPARAM lParam) {
  244.    
  245.    switch (uMsg) {
  246.         HANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
  247.         HANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
  248.         HANDLE_DLGMSG(hwnd, WM_LBUTTONDOWN, Dlg_OnLButtonDown);
  249.    }
  250.  
  251.    return(FALSE);
  252. }
  253.  
  254.  
  255. ////////////////////////////////////////////////////////////
  256.  
  257.  
  258. int APIENTRY WinMain (HINSTANCE hInstance, 
  259.    HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) {
  260.  
  261.     g_hInstance = hInstance;
  262.    DialogBox(hInstance, __TEXT("DLG_DFSRCDEM"), NULL, Dlg_Proc);
  263.    return(0);
  264. }
  265.  
  266.  
  267. ////////////////////////////////////////////////////////////
  268.  
  269.  
  270. // Utility function that parses the list of selected files 
  271. // returned by the File Open Common Dialog Box.
  272. int GetSinglePathName (LPCTSTR szFileOpenStr, int nIndex,
  273.         LPTSTR szPathName, int nMaxLen) {
  274.  
  275.     int nNumFiles = 0, x, y;
  276.     LPCTSTR p = szFileOpenStr, q;
  277.     TCHAR szBuf[200];
  278.  
  279.     // Initialize the buffer by clearing it
  280.     memset(szBuf, 0, sizeof(szBuf));
  281.  
  282.     // Calculate the number of files in szFileOpenStr
  283.    while (*p) {
  284.         if (*p == __TEXT(' ')) nNumFiles++;
  285.       p++;
  286.    }
  287.  
  288.    // If a single file was selected, there are no spaces 
  289.    // but we  should return that one file exists
  290.    if ((nNumFiles == 0) && (p != szFileOpenStr))
  291.         nNumFiles = 1;
  292.  
  293.     // If the user only wants the number of files, return that
  294.    if (nIndex == -1)
  295.         return(nNumFiles);
  296.  
  297.     // User requested more files than exist
  298.    if (nIndex > nNumFiles)
  299.         return(0);
  300.  
  301.    // Construct the full pathname of the requested string
  302.    if ((nIndex == 0) && (nNumFiles == 1)) {
  303.         _tcsncpy(szBuf, szFileOpenStr, nMaxLen);
  304.    } else {
  305.         // Copy the path portion of string into a temp buffer
  306.       x = ((p = _tcschr(szFileOpenStr, __TEXT(' '))) -
  307.           szFileOpenStr);
  308.       _tcsncpy(szBuf, szFileOpenStr, x);
  309.  
  310.       // Append a backslash if necessary
  311.       if (*(p - 1) != __TEXT('\\')) {
  312.             szBuf[x] = __TEXT('\\');
  313.          x++;
  314.       }
  315.  
  316.       for (y = 0; y < nIndex; y++) {
  317.             // Increment past any space so that 'p' 
  318.             // points to a proper filename
  319.             p++;    
  320.          while (*p != __TEXT(' '))
  321.              p++;
  322.       }
  323.       p++;
  324.  
  325.       // Find the end of the filename
  326.       q = _tcschr(p, __TEXT(' '));
  327.  
  328.       if (q != NULL) {
  329.             // Copy the filename into the temp buffer
  330.          _tcsncpy(&szBuf[x], p, (q - p));
  331.       } else {
  332.             // Copy the filename (remainder of string) 
  333.             // into the temp buffer
  334.          _tcscpy(&szBuf[x], p);
  335.       }
  336.    }
  337.  
  338.    if (szPathName != NULL) {
  339.         // If the user passed an address, copy the string into 
  340.         // its buffer and force a zero-termination.
  341.       _tcsncpy(szPathName, szBuf, nMaxLen);
  342.       szPathName[nMaxLen - 1] = 0;
  343.    }
  344.  
  345.    return(_tcslen(szBuf)); // Returns length of string
  346. }
  347.  
  348.  
  349. //////////////////////// End Of File /////////////////////////
  350.